iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0

之前透過有過將匿名函數附值給變數:

var greetFunc = function(name) {
  console.log("hi~" + name)
}

如果想要執行 function 中的程式碼就要透過變數 greetFunc 來呼叫與執行:

var greetFunc = function(name) {
  console.log("hi~" + name)
}

greetFunc("jimmy");

在開發者工具中可以看到 function 執行完畢後預期的輸出內容:

修改一下程式碼:

var greetFunc = function(name) {
  return "hi~" + name;
}

console.log(greetFunc);

會看到開發者工具的 console 中輸出變數 greetFunc 時會是匿名 function 本身:

如果在賦值匿名 function 給變數 greetFunc 時,同時在 {} 結尾處後方加上括號()接著再次呼叫變數 greetFunc:

var greetFunc = function(name) {
  return "hi~" + name;
}("jimmy");

greetFunc();

會看到開發者工具 console 中出現這個錯誤:

原因是因為在匿名 function 後多加了()來在創造 function 後立即執行 function 的程式屬性來執行程式碼,
由於最後是返回字串給變數 greetFunc,
所以呼叫變數 greet 時是在呼叫字串 "hello" 而不是匿名 function,
字串無法被呼叫執行因此出現這個錯誤.

這種在創造匿名 function 時在 {}後增加()來同時執行 function 的寫法稱作立即執行函數表達式(Immediately Invoked Function Expression),比較常直接稱立即執行函數,簡稱 IIFE.

另外如果在全域層級的程式碼區塊新增一些基本型別與物件都不會影響程式碼執行,
在剛才的程式新增一些基本型別的值與物件:

var greetFunc = function(name) {
  return "hi~" + name;
}

console.log(greetFunc);

3;
"a text message";
true;

{name: "jimmy"};


但在全域層級的程式碼區塊直接寫一個匿名 function 呢?

var greetFunc = function(name) {
  return "hi~" + name;
}

console.log(greetFunc);

3;
"a text message";
true;

{name: "jimmy"};

function () {
  console.log("匿名 function");
}

在開發者工具的 console 會出現錯誤:

原因是因為 javascript 引擎在解析程式碼時,逐行逐字解析到 function 這個單字時,
如果發現 function 在那一行的最前面會預期你要宣告的 function 是有名字的.

如果要解決這個錯誤可以將匿名 function 寫在括號中:

(function () {
  console.log("匿名 function");
});

這樣就不會出現錯誤了,

我們也可以直接在匿名 function 的結尾大括號後方透過()括號來立即執行匿名 function:

(function () {
  console.log("立即執行函數 IIFE 被呼叫後執行");
}());

在開發者工具的 console 來驗證:


在很多框架與函式庫中 IIFE 被用來避免不小心將變數添加到全域物件中,
我們已經知道呼叫 function 後會產生自己的執行脈絡,
每個執行脈絡都有自己的變數環境,
因此即使變數名稱相同也能夠不互相影響,

我們一樣透過一段程式碼來解釋:

var ourMemory = "第一次遇見你";

(function () {
  var ourMemory = "最後一次擁抱你";
  console.log("IIFE 中的 ourMemory: " + ourMemory);
}());

console.log("Window 中的 ourMemory: " + ourMemory);

在開發者工具 console 中結果:

不過如果是刻意要改變全域物件 window 中的屬性(全域變數)也是可以,
只要將全域物件 window 當作參數傳入 IIFE :

var ourMemory = "第一次遇見你";

(function (global) {
  var ourMemory = "最後一次擁抱你";
  console.log("IIFE 中的 ourMemory: " + ourMemory);

  global.ourMemory = "曾經的開心與難過都有你參與";
}(window));

console.log("Window 中的 ourMemory: " + ourMemory);

在開發者工具 console 中結果:


上一篇
What's this?
下一篇
閉包
系列文
那些必須了解的 JavaScript 特性與寫程式前的思考17
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言